# Copyright 2007 Pete Lypkie, Jonathon Trivett
# This file is part of Luqi
#
# Luqi is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Luqi is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Luqi; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


# 1) pop up a window with a picture in it.
# 2) user can click the image and coords are printed on the command line
# 3) when user clicks, a dot is drawn where they clicked.  4 clicks allowed.
# 4) add reset-clicks button that erases dots to start over.

import CamImage
from Tkinter import *
from PIL import Image, ImageTk, ImageDraw
from tkSimpleStatusBar import StatusBar


# Window is created with a canvas, several buttons, and a status bar.
# The canvas holds the image of the board and allows people to draw shit.
# The buttons are quit, reset, and choose corners.  Reset sets the image
#   back to the original with no corners chosen.  Choose corners sets it up
#   so that the user can pick the corners.

class CornerChooserGui:
    
    def __init__(self, master):
        "add a basic frame for this object and put a quit button in."
        self._master = master
        self._master.bind_all("<Key>", self.keypress)
        self._frame = Frame(self._master)
        self._frame.pack()
        self._status = StatusBar(self._frame)
        self._status.pack(side=BOTTOM, fill=X)
        self._savedimage = None
        self._image = None
        self._draw = None
        self._choosecorners = False
        self._imageindex = 0
        self._imagelist = ["TestImages/emptyboard.jpg",
                           "TestImages/oneblackstone.jpg",
                           "TestImages/oneblackonewhite.jpg",
                           "TestImages/twoblackonewhite.jpg",
                           "TestImages/4black7white.jpg",
                            "TestImages/4black7whitewithhand.jpg"]
        self._numpoints = 0
        self._points = []
        self.photo = None
        self._quitbutton = Button(self._frame, 
                                  text="Quit", 
                                  command=self._frame.quit)
        self._quitbutton.pack(side=BOTTOM)
        self._resetbutton = Button(self._frame, 
                                   text="Reset Image", 
                                   command=self.resetimage)
        self._resetbutton.pack(side=BOTTOM)
        self._cycleimagebutton = Button(self._frame,
                                       text="cycle to next image",
                                       command=self.cycleimage)
        self._cycleimagebutton.pack(side=BOTTOM)
        self._boardbutton = Button(self._frame, 
                                     text="show the board",
                                     command=self.displayboard)
        self._boardbutton.pack(side=BOTTOM)
        self._gridbutton = Button(self._frame, text="show grid",
                                   command=self.displaygrid)
        self._gridbutton.pack(side=BOTTOM)
        self._transformbutton = Button(self._frame,
                                       text="transform image",
                                       state='disabled',
                                       command=self.transform)
        self._transformbutton.pack(side=BOTTOM)
        self._choosepointsbutton = Button(self._frame, 
                                          text="Choose corners", 
                                          command=self.choosecorners_enable)
        self._choosepointsbutton.pack(side=BOTTOM)

        self._canvas = Canvas(self._frame, width=640, height=480, bg='white')
        self._canvas.bind("<Button-1>", self.click)
        self._canvas.pack()
        

    def get4points(self, filename):
        """Start the gui and ask the user for 4 points for the corners

        Use this function to start up the gui and gather the 4 points.
        They'll be returned as a tuple of 4 (x,y) pairs.

        Example code:
        root = Tk()
        foo = CornerChooserGui(root)
        mypoints = foo.get4points("somefile.jpg")
        dostuff(mypoints)"""

        self.loadImage(filename)
        self._master.mainloop()
        if self._numpoints == 4:
            return (self._points[0], 
                    self._points[1],
                    self._points[2],
                    self._points[3])
        else:
            return ((0,0),(0,0),(0,0),(0,0))


    def transform(self):
        """Use the 4 points chosen by the user to transform the image and redisplay it"""

        pointdata = (self._points[0][0], self._points[0][1],
                     self._points[1][0], self._points[1][1],
                     self._points[2][0], self._points[2][1],
                     self._points[3][0], self._points[3][1])
        # use the savedimage to produce the transformation
        # so that the red dots don't get in there
        self._image = self._savedimage.transform((480,480), 
                                                 Image.QUAD, 
                                                 pointdata)
        self.setImage(self._image)
        self.setstatus("transformed the image.  should be a square now")
    #end of transform

    def cycleimage(self):
        # go through the list of images to the next one, looping back
        # after the end.
        self._imageindex += 1
        if self._imageindex >= len(self._imagelist):
            self._imageindex = 0
        self.loadImage(self._imagelist[self._imageindex])


    def displaygrid(self):
        """use a CamImage to get a thresholded image and display it"""
        myimg = CamImage.CamImage(self._image)
        self.setImage(myimg.gridimage())


    def displayboard(self):
        """use CamImage to find the board in the image"""
        myimg = CamImage.CamImage(self._image)
        self.setImage(myimg.boardimage())

    def loadImage(self, filename):
        "load an image from a file and set that as the current image"
        self.setstatus("Loading image from file")
        self._savedimage = Image.open(filename)
        self.resetimage()
        
    def setImage(self, image):
        self.photo = ImageTk.PhotoImage(image)
        self.setstatus("Displaying new image...")
        self._canvas.delete("image")
        self._canvas.create_image(0,0,image=self.photo, anchor=NW, tag="image")

    def resetimage(self):
        """put back original unmodified image and turn off choosing mode"""
        if self._savedimage != None:
            self.setImage(self._savedimage)
            self._image = self._savedimage.copy()
        self.choosecorners_disable()
        self._draw = None
        self._points = []
        self._numpoints = 0
        self._transformbutton['state'] = 'disabled'
        
    def choosecorners_enable(self):
        """activate ability to draw dots on image"""
        self._choosecorners = True
        # should do something with the button to indicate mode is on
        
    def choosecorners_disable(self):
        """deactivate ability to draw."""
        self._choosecorners = False
        # should do something with the button to indicate mode is off
            
    def setstatus(self, string):
        """change message on status bar at the bottom"""
        print string
        self._status.set("%s", string)
        
    def clearstatus(self):
        print "Cleared status bar."
        self._status.clear()

    def click(self, event):
        self.display_coords(event)
        if self._choosecorners == True:
            self.pickpoint(event.x, event.y)

    def pickpoint(self, x, y):
        if self._numpoints < 4:
            self.drawcorner(x, y)
            self._numpoints += 1
            self._points.append((x, y))
            if self._numpoints == 4:
                self._transformbutton['state'] = 'normal'
        else:
            self.setstatus("Already have 4 points chosen.  Hit reset to try again, or Quit to finish.")
        
            
    def drawcorner(self, x, y):
        print "draw at (%i, %i)" % (x, y)
        if self._draw == None:
            self._draw = ImageDraw.Draw(self._image)
        self._draw.rectangle(((x-2, y-2), (x+2, y+2)), fill="#ff0000", outline="#ff0000")
        self.setImage(self._image)
        
    def display_coords(self, event):
        "spit out coords"
        self.setstatus("last spot clicked: %i, %i" % (event.x, event.y))

    def keypress(self, event):
        if event.char == "q":
            self.quit()

    def clear(self):
        self._points = []
        self._numpoints = 0
        self._image = None
        self._savedimage = None
        self.photo = None
        self._draw = None
        self._choosecorners = False
        
    def quit(self):
        self.setstatus("Quitting...")
        self._master.destroy()
        
        

# stuff to make this file run itself:
root = Tk()
app = CornerChooserGui(root)
print app.get4points("./TestImages/twoblackonewhite.jpg")

